#include "Thread.hpp"
using namespace MyThread;
#include <iostream>
using namespace std;
#include <vector>
#include <string>
#include <unistd.h>
#include "RingQueue.hpp"
#include "BlockQueue.hpp"

template<class T>
using blockqueue_t = blockqueue<T>;

void ProducerCore(blockqueue_t<int>& bq)
{
    int cnt = 10;
    while (true)
    {
        bq.Enqueue(cnt);
        cout << "Producer" << " send a task : " << cnt-- << endl;
        sleep(1);
    }
}

void ConsumerCore(blockqueue_t<int>& bq)
{
    sleep(3);
    while (true)
    {
        int data = 0;
        bq.Pop(&data);
        cout << "Consumer" << " execute the task : " << data << endl;
    }
}

void Producer(vector<Thread<blockqueue_t<int>>> &threads, blockqueue_t<int> &bq, int threadnum)
{
    for (int num = 0; num < threadnum; num++)
    {
        string name = "producer-" + to_string(num + 1);
        // threads.push_back(Thread<blockqueue_t>(*bq, ProducerCore, name));
        threads.emplace_back(bq, ProducerCore, name);
    }
}

void Consumer(vector<Thread<blockqueue_t<int>>> &threads, blockqueue_t<int> &bq, int threadnum)
{
    for (int num = 0; num < threadnum; num++)
    {
        string name = "consumer-" + to_string(num + 1);
        // threads.push_back(Thread<blockqueue_t>(*bq, ConsumerCore, name));

        threads.emplace_back(bq, ConsumerCore, name);
    }
}

void StartAll(vector<Thread<blockqueue_t<int>>> &threads)
{
    for (auto &thread : threads)
    {
        thread.Start();
    }
}

void WaitAll(vector<Thread<blockqueue_t<int>>> &threads)
{
    for (auto &thread : threads)
    {
        thread.Join();
    }
}

int main()
{
    blockqueue_t<int> *bq = new blockqueue_t<int>(5);
    vector<Thread<blockqueue_t<int>>> threads;

    Producer(threads, *bq, 1);
    Consumer(threads, *bq, 1);

    StartAll(threads);

    WaitAll(threads);

    return 0;
}